package com.redhipps.hips.client.widget;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Widget;
import com.redhipps.hips.client.controller.EditCallback;
import com.redhipps.hips.client.controller.ModelEditDelegate;
import com.redhipps.hips.client.io.IOService;
import com.redhipps.hips.client.io.WriterCallback;
import com.redhipps.hips.client.model.Context;
import com.redhipps.hips.client.model.Doctor;
import com.redhipps.hips.client.model.DoctorConstraint;
import com.redhipps.hips.client.model.ModelRepository;


public class DoctorConstraintList extends ModelList<DoctorConstraint> {

  private static String[] HEADERS = { "Name", "Login", "Days off",
      "Min shifts", "Max shifts", "Max night shifts", "Max consecutive days", "Edit" };

  private ModelRepository<Doctor> doctors;

  public DoctorConstraintList(Context ctx, List<DoctorConstraint> values,
      ModelRepository<Doctor> doctors, IOService ioService) {
    super(ctx, values);
    setEditingDelegate(new DoctorConstraintListEditDelegate(ioService));
    this.doctors = doctors;
    refresh();
  }
  
  @Override
  protected Object[] headers() {
    return HEADERS;
  }

  @Override
  protected Object[] writeModel(final DoctorConstraint model, int row) {
    Object[] values = new Object[8];
    final Doctor doctor = doctors.get(model.getDoctorRef());
    Hyperlink hyperlink = new Hyperlink(doctor.getName(), "doctorList");
    hyperlink.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        context().pushDoctor(doctor);
      }
    });
    values[0] = hyperlink;
    values[1] = doctor.getLogin();
    StringBuilder b = new StringBuilder();
    List<?> listValue = model.getDaysOff();
    for (int i = 0; i < listValue.size(); i++) {
      b.append(listValue.get(i));
      if (i < listValue.size() - 1) {
        b.append(", ");
      }
    }
    values[2] = b.toString();
    values[3] = model.getMinShifts();
    values[4] = model.getMaxShifts();
    values[5] = model.getMaxNightShifts();
    values[6] = model.getMaxConsecutiveDays();
    Button editButton = new Button("Edit...");
    ClickListener l = createModelEditClickListener(model);
    editButton.addClickListener(l);
    values[7] = editButton;
    return values;
  }

  private class DoctorConstraintListEditDelegate implements
      ModelEditDelegate<DoctorConstraint> {

    private IOService ioService;

    public DoctorConstraintListEditDelegate(IOService ioService) {
      this.ioService = ioService;
    }

    public void createModel(Context context, EditCallback<DoctorConstraint> callback) {
      // Not supported
    }

    public void deleteModel(Context context, DoctorConstraint model,
        EditCallback<DoctorConstraint> callback) {
      // Not supported
    }

    public void editModel(final Context context, final DoctorConstraint model,
        final EditCallback<DoctorConstraint> callback) {
      // TODO Centralize model creation/editing logic.
      AsyncCallback<String> dialogCallback = new AsyncCallback<String>() {
        public void onFailure(Throwable caught) {
          GWT.log("DoctorConstraint write failed", caught);
        }
        public void onSuccess(String result) {
          if (result == null) {
            return;
          }
          String[] listHalves = result.split("] *,");

          // Days off
          String daysOffList = listHalves[0].substring(1);
          String[] daysOffStrList = daysOffList.split(" *, *");
          List<Integer> daysOffIntList = new ArrayList<Integer>();
          for (String s : daysOffStrList) {
            daysOffIntList.add(new Integer(s));
          }
          model.setDaysOff(daysOffIntList);

          // Additional properties
          String[] attrList = listHalves[1].split(" *, *");
          model.setMinShifts(Integer.parseInt(attrList[0]));
          model.setMaxShifts(Integer.parseInt(attrList[1]));
          model.setMaxNightShifts(Integer.parseInt(attrList[2]));
          model.setMaxConsecutiveDays(Integer.parseInt(attrList[3]));

          ioService.write(context, model, new WriterCallback<DoctorConstraint>() {
            public void onFailure(Throwable caught) {
              GWT.log("Failed to save constraint.", caught);
              callback.onFailure(caught);
            }
            public void onSuccess(List<DoctorConstraint> result) {
              GWT.log("Saved edited constraint: " + result, null);
              callback.onSuccess(model);
            }
          });
        }
      };
      Dialogs.answer("Constraint",
          "[days off], min_shifts, max_shifts, max_night_shifts, max_consecutive_days",
          dialogCallback);
    }
    
  }
}
